﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using MergeTool.ClassLib;
using MergeTool.ClassLib.Configuration;
using MergeTool.UI.ViewModels;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.VersionControl.Common;
using ValidationResult = System.ComponentModel.DataAnnotations.ValidationResult;

namespace MergeTool.UI.Helpers
{
    public class ImmediateMerge : MyCustomViewModelBase
    {
        private ICollectionView availableBranches;

        public ICollectionView AvailableBranches
        {
            get
            {
                return this.availableBranches;
            }
        }

        private string _selectedBranchFrom;

        public string SelectedBranchFrom
        {
            get
            {
                return this._selectedBranchFrom;
            }
            set
            {
                this._selectedBranchFrom = value;
                if (!string.IsNullOrEmpty(value))
                {
                    this.FromPath = value;
                }
            }
        }

        private string _selectedBranchTo;

        public string SelectedBranchTo
        {
            get
            {
                return this._selectedBranchTo;
            }
            set
            {
                this._selectedBranchTo = value;
                if (!string.IsNullOrEmpty(value))
                {
                    this.ToPath = value;
                }
            }
        }

        private bool _isShowAutoCompleteFrom;

        public bool IsShowAutoCompleteFrom
        {
            get { return this._isShowAutoCompleteFrom; }
            set
            {
                SetProperty(ref _isShowAutoCompleteFrom, value);
            }
        }

        private bool _isShowAutoCompleteTo;

        public bool IsShowAutoCompleteTo
        {
            get { return this._isShowAutoCompleteTo; }
            set
            {
                SetProperty(ref _isShowAutoCompleteTo, value);
            }
        }

        public ImmediateMerge()
        {
            this.MergeOption = MergeOptionsEx.Conservative;
            
            this.availableBranches = CollectionViewSource.GetDefaultView(new BranchManager().GetAllNonDeletedBranchObjects().Select(br => br.Properties.RootItem.Item));

            if (Settings.GetInstance().IsMergeByChangesets)
            {
                this.CheckinCommentPattern = Settings.GetInstance().DefaultChangesetCheckinCommentPattern;
            }
            else
            {
                this.CheckinCommentPattern = Settings.GetInstance().DefaultBranchCheckinCommentPattern;
            }

            
        }

        private MergeOptionsEx _mergeOption;

        public MergeOptionsEx MergeOption
        {
            get { return _mergeOption; }
            set
            {
                SetProperty(ref _mergeOption, value);
            }
        }

        private bool IsMerging;

        public string FromPath
        {
            get { return this._fromPath; }
            set
            {
                SetProperty(ref _fromPath, value);
                if (value != this._selectedBranchFrom && !IsMerging)
                {
                    this.IsShowAutoCompleteFrom = true;
                    this.availableBranches.Filter = ContainsBranchFrom;
                    AvailableBranches.Refresh();
                }
                else
                {
                    this.IsShowAutoCompleteFrom = false;
                }
            }
        }

        private bool ContainsBranchFrom(object item)
        {
            var fromItem = item as string;
            if (fromItem == null)
            {
                return false;
            }

            if (string.IsNullOrEmpty(this.FromPath))
            {
                return true;
            }

            if (fromItem.ToUpperInvariant().Contains(this.FromPath.ToUpperInvariant()))
            {
                return true;
            }

            return false;
        }

        public string ToPath
        {
            get { return this._toPath; }
            set
            {
                SetProperty(ref _toPath, value);
                if (value != this._selectedBranchTo && !IsMerging)
                {
                    this.IsShowAutoCompleteTo = true;
                    this.availableBranches.Filter = ContainsBranchTo;
                    AvailableBranches.Refresh();
                }
                else
                {
                    this.IsShowAutoCompleteTo = false;
                }
            }
        }

        public string CheckinCommentPattern
        {
            get { return this._checkinCommentPattern; }
            set
            {
                SetProperty(ref _checkinCommentPattern, value);
            }
        }

        private bool ContainsBranchTo(object item)
        {
            var toItem = item as string;
            if (toItem == null)
            {
                return false;
            }

            if (string.IsNullOrEmpty(this.ToPath))
            {
                return true;
            }

            if (toItem.ToUpperInvariant().Contains(this.ToPath.ToUpperInvariant()))
            {
                return true;
            }

            return false;
        }

        public int ChangesetIdToStartFrom
        {
            get { return this._changesetIdToStartFrom; }
            set { SetProperty(ref _changesetIdToStartFrom, value); }
        }

        private string _fromPath;
        private string _toPath;
        private string _checkinCommentPattern;
        private int _changesetIdToStartFrom;

        public async Task StartMergingSpecific(BranchManager branchManager, MergeToolViewModel mergeToolViewModel)
        {
            MergeManager mergeManager = new MergeManager();
            PopulatePaths(branchManager);
            mergeToolViewModel.PrintMergingStarted();
            mergeToolViewModel.PrintBranchMergeBegin(FromPath, this.ToPath);
            MergeObjectLink mergeObjectLink = new MergeObjectLink();
            try
            {
                if (Settings.GetInstance().IsMergeByChangesets || MainViewModel.StaticIsMergeMultipleSpecifiedChangesets)
                {
                    var mergeCandidates = mergeManager.GetMergeCandidates(this.FromPath, this.ToPath, this.MergeOption, this.ChangesetIdToStartFrom);

                    if (MainViewModel.StaticIsMergeMultipleSpecifiedChangesets)
                    {
                        mergeCandidates = mergeManager.ParseMultipleChangesetsTextBox(MainViewModel.StaticExplicitChangesetArray, mergeCandidates);
                    }

                    foreach (MergeCandidate t in mergeCandidates)
                    {
                        mergeToolViewModel.PrintChangesetMergeBegin(t.Changeset.ChangesetId.ToString(), this.FromPath,
                            this.ToPath);

                        mergeObjectLink = mergeManager.MergeByChangeset(this.FromPath,
                            this.ToPath, t.Changeset, this.MergeOption, this.CheckinCommentPattern, this.ChangesetIdToStartFrom);

                        mergeToolViewModel.ProceedAfterMerge(mergeObjectLink, mergeManager);


                        mergeToolViewModel.PrintChangesetMergeEnd(t.Changeset.ChangesetId.ToString(), this.FromPath,
                            this.ToPath, mergeObjectLink);
                    }
                }
                else
                {
                    mergeObjectLink = mergeManager.MergeByBranch(this.FromPath, this.ToPath, this.MergeOption, this.CheckinCommentPattern, this.ChangesetIdToStartFrom);
                    mergeToolViewModel.ProceedAfterMerge(mergeObjectLink, mergeManager);
                }
            }
            catch (Exception ex)
            {
                mergeToolViewModel.PrintErrorDuringMerge(ex);
            }
            mergeToolViewModel.PrintBranchMergeEnd(FromPath, this.ToPath, mergeObjectLink);
            mergeToolViewModel.PrintMergingEnded();
        }

        internal void PopulatePaths(BranchManager branchManager)
        {
            IsMerging = true;
            this.ToPath = branchManager.GetFullPathForBranch(this.ToPath);
            this.FromPath = branchManager.GetFullPathForBranch(this.FromPath);
            IsMerging = false;
        }
    }
}
